Java.perform(function () {
    console.log("注入成功,请操作触发hook");
    // 1. 配置日志文件路径（Android 推荐 /sdcard/ 目录，无需 root）
    const LOG_FILE_PATH = "/sdcard/InsLog/";
    const FileOutputStream = Java.use("java.io.FileOutputStream");
    var Gson = Java.use('com.google.gson.Gson');
    var gson = Gson.$new();
    function dumpInstance(instance) {
        try {
            var jclazz = instance.getClass();
            var className = jclazz.getName();
            console.log(`\n====== 开始打印实例 ${className}@${instance.hashCode()} 的信息 ======`);

            // --- 打印字段 ---
            console.log("  [+] 字段 (Fields):");
            var fields = jclazz.getDeclaredFields();
            if (fields.length === 0) {
                console.log("无字段");
            } else {
                fields.forEach(function (field) {
                    try {
                        // 修正：对单个 field 设置 setAccessible
                        field.setAccessible(true);

                        var fieldName = field.getName();
                        var fieldType = field.getType().getName();

                        // 核心修正：从 instance 对象中获取字段值
                        var fieldValue = field.get(instance);

                        // 对值进行更友好的展示
                        var fieldValueStr = fieldValue;
                        if (fieldValue && typeof fieldValue.toString === 'function') {
                            try {
                                //fieldValueStr = fieldValue.toString();
                                fieldValueStr = gson.A0A(fieldValueStr);
                            } catch (e) {
                                // toString 可能会失败，例如对于一些代理类
                                fieldValueStr = `[无法调用 toString(): ${e.message}]`;
                            }
                        }

                        console.log(` =======${fieldName}  (${fieldType}): ${fieldValueStr}`);
                    } catch (e) {
                        console.log(`    获取字段 ${field.getName()} 的值失败: ${e.message}`);
                    }
                });
            }

            // --- 打印方法 ---
            console.log("\n  [+] 方法 (Methods):");
            var methods = jclazz.getDeclaredMethods();
            if (methods.length === 0) {
                console.log("    无方法");
            } else {
                methods.forEach(function (method) {
                    var methodName = method.getName();
                    var returnType = method.getReturnType().getName();
                    var parameterTypes = method.getParameterTypes().map(function (p) { return p.getName(); }).join(", ");
                    console.log(`    ${methodName}(${parameterTypes}): ${returnType}`);
                });
            }
            console.log(`====== 实例 ${className}@${instance.hashCode()} 信息打印完毕 ======\n`);

        } catch (e) {
            console.log(`dumpInstance 失败：${e.stack}`);
        }
    }

    function printA03GzipBody(instance) {
        try {
            // 第1层：找到 A08 字段
            var fields1 = instance.getClass().getDeclaredFields();
            var A08 = null;
            var a08Count = 0;
            for (var i = 0; i < fields1.length; i++) {
                console.log("第1层字段: " + fields1[i].getName());
                if (fields1[i].getName() === "A08") {
                    fields1[i].setAccessible(true);
                    A08 = fields1[i].get(instance);
                    // break;
                    a08Count++;
                }
            }
            console.log("a08Count: " + a08Count);
            if (!A08) {
                console.log("[-] 未找到 A08");
                return;
            }

            // 第2层：A08 里面的 A06
            var fields2 = A08.getClass().getDeclaredFields();
            var A06 = null;
            var a06Count = 0;
            for (var i = 0; i < fields2.length; i++) {
                console.log("第2层字段: " + fields2[i].getName());
                if (fields2[i].getName() === "A06") {
                    fields2[i].setAccessible(true);
                    A06 = fields2[i].get(A08);
                    console.log("A06: " + A06);
                    a06Count++;
                    // break;
                }
            }
            console.log("a06Count: " + a06Count);
            if (!A06) {
                console.log("[-] 未找到 A06");
                return;
            }

            // 第3层：A06 里面的 A03（byte[]）
            var fields3 = A06.getClass().getDeclaredFields();
            var A03_bytes = null;
            for (var i = 0; i < fields3.length; i++) {
                if (fields3[i].getName() === "A03") {
                    fields3[i].setAccessible(true);
                    A03_bytes = fields3[i].get(A06);   // 这就是 byte[]
                    break;
                }
            }
            if (!A03_bytes) {
                console.log("[-] 未找到 A03");
                return;
            }

            console.log("[+] 成功拿到 gzip body，长度: " + A03_bytes.length + " bytes");

            // ---------- 直接打印为 hex（调试用） ----------
            var hex = "";
            var arr = Java.array('byte', A03_bytes);
            for (var j = 0; j < Math.min(arr.length, 256); j++) {  // 前256字节就够判断了
                hex += (arr[j] & 0xFF).toString(16).padStart(2, '0') + " ";
                if (j % 16 === 15) hex += "\n";
            }
            console.log("Hex 前256字节:\n" + hex);

            // ---------- 解压成明文（最想要的） ----------
            console.log("[+] 正在解压 gzip...");
            var plain = ungzipToString(A03_bytes);
            console.log("\n【明文 Body】\n" + plain.substring(0, 4000) + (plain.length > 4000 ? "\n...[已截断]" : ""));

        } catch (e) {
            console.log("[-] 异常: " + e);
            console.log(e.stack);
        }
    }

    try {

        // var G1A = Java.use("X.G1A");
        // G1A.run.implementation = function(){
        //     //console.log("run被调用");
        //     try {
        //         var vfp = Java.cast(this.A00.value , Java.use("X.VfP"));

        //         // //console.log("[+] 字段A00 vfp的值："+ vfp);
        //         var vfpA08 = vfp.A08.value;
        //         var j7tA08= vfpA08.A08.value;

        //         if(j7tA08.toString().indexOf("fbsearch/reels_serp") !== -1){
        //             printA03GzipBody(vfp)

        //             // var vfpClass = vfp.getClass();
        //             // var vfpA08s = vfpClass.getDeclaredField("A08");
        //             // vfpA08s.setAccessible(true);
        //             // var vfpA08Value =vfpA08s.get(vfp);
        //             // var vfpA08ValueClass = vfpA08Value.getClass();
        //             // var vfpA08ValueClassFieldA06 = vfpA08ValueClass.getDeclaredField("A06");
        //             // vfpA08ValueClassFieldA06.setAccessible(true);
        //             // var vfpA08ValueClassFieldA06Value = vfpA08ValueClassFieldA06.get(vfpA08Value);
        //             // var vfpA08ValueClassFieldA06ValueClass = vfpA08ValueClassFieldA06Value.getClass();
        //             // console.log("具体实现的类："+vfpA08ValueClassFieldA06ValueClass);
        //             // vfpA08ValueClassFields.forEach(function(field) {
        //             //     try {
        //             //         field.setAccessible(true);
        //             //         var fieldName = field.getName();
        //             //         var fieldType = field.getType().getName();
        //             //         var fieldValue = field.get(vfpA08Value);
        //             //         console.log("[+] 字段名："+fieldName+"  字段类型："+fieldType+"  字段值："+fieldValue);
        //             //     } catch (e) {
        //             //         console.log("获取字段失败：" + e.message);
        //             //     }
        //             // })
        //             // var vfpA08ValueGson = gson.A0A(vfpA08Value);
        //             // console.log("[+] vfpA08ValueGson的值："+vfpA08ValueGson);
        //             // var A03obj = JSON.parse(vfpA08ValueGson);
        //             // console.log("[+] A03obj的值："+A03obj.A06.A03);
        //             // var byteObj = Java.array('byte', A03obj.A06.A03)
        //             // console.log("转字符串："+StringCls.$new(byteObj, "UTF-8"));



        //             //dumpInstance(vfp);
        //             // var vfpClass =vfp.getClass()
        //             // console.log("[+] j7tA08的值："+ j7tA08);
        //             // var vfpA02 =vfp.A02.value;
        //             // console.log("[+] A02的类型是："+vfpA02);
        //             // var vfpClass = vfp.getClass();
        //             // var vfpA02= vfpClass.getDeclaredField("A02");
        //             // vfpA02.setAccessible(true);
        //             // var vfpA02Value =vfpA02.get(vfp);
        //             // if(vfpA02Value){
        //             //     console.log("[+] vfpA02Value的值："+vfpA02Value);
        //             //     console.log("[+] str:"+vfpA02Value.toString());

        //             //     var vfpA02ValueClass = vfpA02Value.getClass();
        //             //     console.log("实现接口的类名是："+vfpA02ValueClass.getName());
        //             // }
        //             // var vfpA06= vfpClass.getDeclaredField("A06");
        //             // vfpA06.setAccessible(true);
        //             // var vfpA06Value =vfpA06.get(vfp);
        //             // //console.log("[+] vfpA06的值："+vfpA06Value);
        //             // console.log("[+] gons A06 "+ gson.A0A(vfpA06Value));
        //             // var vfpA06ValueClass = vfpA06Value.getClass();
        //             // console.log("实现接口的类名是："+vfpA06ValueClass.getName());

        //         }
        //     } catch (e) {
        //         console.log("hook run方法失败："+e.stack)
        //     }
        //     return this.run();
        // }

        //     var YEA = Java.use("X.YEA");
        //     YEA.onBody.implementation = function (byteBuffer) {
        //         // console.log('X.YEA.onBody called'); // 防止刷屏，先注释掉

        //         try {
        //             // 1. 获取 A09 字段 (下一个接力棒)
        //             // 如果直接 .value 报错 undefined，就用反射 (同之前的逻辑)

        //             // 这里先尝试直接拿
        //             var nextHandler = this.A09.value; 

        //             if (!nextHandler) {
        //                 // 如果 undefined，尝试反射获取
        //                 var f = this.getClass().getDeclaredField("A09"); // 确认 Jadx 里是叫 A09
        //                 f.setAccessible(true);
        //                 nextHandler = f.get(this);
        //             }

        //             if (nextHandler) {
        //                 var nextClassName = nextHandler.$className;

        //                 // 打印一次就够了，避免刷屏
        //                 // 我们可以用一个全局 Set 来记录已打印过的类
        //                 // 这里为了简单，直接打印

        //                 // 只有当我们还没有识别出解压类时才打印
        //                 console.log("========================================");
        //                 console.log("[*] 当前层级: X.YEA");
        //                 console.log("[*] 下一层级 (A09): " +nextClassName);
        //                 console.log("========================================");
        //             }

        //         } catch(e) {
        //             console.log("Error inspecting A09: " + e.stack);
        //         }

        //     this.onBody(byteBuffer);
        // };



        // var YEA = Java.use("X.YEA");
        // var YDz = Java.use("X.YDz"); 
        // YEA.onBody.overload('java.nio.ByteBuffer').implementation = function(buff) {

        //     // 为了防止刷屏，我们只在第一次调用，或者每隔几百次调用打印一次
        //     // 或者简单点，只打印前几次
        //     // if (this._hasPrinted == undefined) {

        //     //     try {
        //     //         // 1. 拿到 X.YDz 对象 (即 A09)
        //     //         var nextHandlerObj = this.A09.value;

        //     //         if (nextHandlerObj) {
        //     //             // 2. 强转为 X.YDz 类型，这样才能访问它的字段 A08
        //     //             var ydzInstance = Java.cast(nextHandlerObj, YDz);

        //     //             // 3. 【关键】拿到 X.YDz 里的 A08 字段
        //     //             var finalTarget = ydzInstance.A08.value;

        //     //             if (finalTarget) {
        //     //                 var finalClassName = finalTarget.$className;
        //     //                 console.log("========================================");
        //     //                 console.log("[+] 链路追踪成功！");
        //     //                 console.log("[+] YEA -> YDz -> ???");
        //     //                 console.log("[+] YDz 的下一级 (A08) 真实类名是: " + finalClassName);
        //     //                 console.log("========================================");

        //     //                 // 标记已打印，后面不再刷屏
        //     //                 this._hasPrinted = true; 
        //     //             } else {
        //     //                 console.log("[-] YDz.A08 是 null，这不合理...");
        //     //             }
        //     //         }
        //     //     } catch (e) {
        //     //         console.log("[!] 追踪出错: " + e);
        //     //     }
        //     // }
        //     // 2. 获取 A01 字段 (下一级 Handler)
        //     try {
        //         var nextHandler = this.A01.value;

        //         if (nextHandler) {
        //             var nextName = nextHandler.$className;

        //             // 防止刷屏，我们只打印一次
        //             if (this._printed == undefined) {
        //                 console.log("========================================");
        //                 console.log("[+] 当前层级: X.YDA (线程检查)");
        //                 console.log("[+] 下一层级 (A01) 类名: " + nextName);
        //                 console.log("========================================");
        //                 this._printed = true;
        //             }
        //             //dumpInstance(nextHandler);
        //         }
        //     } catch(e) {
        //         console.log("Error: " + e);
        //     }
        //     // 记得调用原始方法，不然数据就断了，APP会报错
        //     this.onBody(buff);
        // }

        // let G1O = Java.use("X.G1O");
        // G1O["run"].implementation = function () {
        //     console.log('run is called');
        //     var vfp = Java.cast(this.A00.value , Java.use("X.VfP"));


        //     var vfpA08 = vfp.A08.value;
        //     var j7tA08= vfpA08.A08.value;
        //         if(j7tA08.toString().indexOf("fbsearch/reels_serp") !== -1){
        //             dumpInstance(vfp)
        //         }
        //     let ret = this.run();
        //     console.log('run ret value is ' + ret);
        //     return ret;
        // };

        function copy_byte(bArr, off, ret) {
            const FileOutputStream = Java.use("java.io.FileOutputStream");
            // 正确获取 files 目录
            const ctx = Java.use("android.app.ActivityThread")
                .currentApplication()
                .getApplicationContext();

            const dumpFile = Java.use("java.io.File").$new(ctx.getFilesDir(), "proxygen_dump_all.bin");
            const fos = FileOutputStream.$new(dumpFile, true);  // append = true

            // 防止被 GC
            globalThis.__dump_fos = fos;

            console.log("[*] Proxygen dump start → " + dumpFile.getAbsolutePath());
            try {
                fos.write(bArr, off, ret);
                // 每 256KB 打印一次进度，避免刷屏
                if (fos.getChannel().size() % (256 * 1024) < 1024) {
                    console.log("[+] Dumped: " + (fos.getChannel().size() / 1024 / 1024).toFixed(2) + " MB");
                }
            } catch (e) {
                console.log("[-] Write failed: " + e);
            }
        }

        function hook_NativeReadBuffer_Run() {
            const NativeReadBuffer = Java.use("com.facebook.proxygen.NativeReadBuffer");
            const FileOutputStream = Java.use("java.io.FileOutputStream");

            // 正确获取 files 目录
            const ctx = Java.use("android.app.ActivityThread")
                .currentApplication()
                .getApplicationContext();

            const dumpFile = Java.use("java.io.File").$new(ctx.getFilesDir(), "proxygen_dump_all.bin");
            const fos = FileOutputStream.$new(dumpFile, true);  // append = true

            // 防止被 GC
            globalThis.__dump_fos = fos;

            console.log("[*] Proxygen dump start → " + dumpFile.getAbsolutePath());

            NativeReadBuffer.read.implementation = function (bArr, off, len) {
                const ret = this.read(bArr, off, len);
                if (ret > 0) {
                    try {
                        fos.write(bArr, off, ret);
                        // 每 256KB 打印一次进度，避免刷屏
                        if (fos.getChannel().size() % (256 * 1024) < 1024) {
                            console.log("[+] Dumped: " + (fos.getChannel().size() / 1024 / 1024).toFixed(2) + " MB");
                        }
                    } catch (e) {
                        console.log("[-] Write failed: " + e);
                    }
                }
                return ret;
            };
        }



        function hook_G01_run() {
            var body_data = []
            let G1A = Java.use("X.G1A");
            const FileOutputStream = Java.use("java.io.FileOutputStream");
            G1A["run"].implementation = function () {
                try {
                    var vfP = Java.cast(this.A00.value, Java.use("X.VfP"));
                    var vfpA08 = vfP.A08.value;
                    var j7tA08 = vfpA08.A08.value;
                    if (j7tA08.toString().indexOf("fbsearch/reels_serp") !== -1) {
                        var vfP = this.A00.value;
                        var readBuffer = vfP.A06.value;
                        //readBufferCopy =Java.cast(Java.use("com.facebook.proxygen.NativeReadBuffer"),readBufferCopy); 
                        //console.log("url:" + j7tA08.toString());
                        console.log('readBuff is ' + gson.A0A(readBuffer));
                        const ByteBuffer = Java.use("java.nio.ByteBuffer");
                        const buffer = ByteBuffer.allocate(4096);
                        var allocate = Java.cast(buffer, ByteBuffer.allocate(4096));
                        console.log("allocate: " + allocate);
                        //console.log('allocate gson: ' + gson.A0A(allocate));
                        var size = readBuffer.size();
                        console.log("size:" + size);
                        while (size > 0) {
                            vfP.A00 += size
                            console.log("vfP.A06 类名:" + readBuffer.$className);
                            try {
                                var arr = allocate.array();
                                var allocatebyte = Java.array("byte", arr);
                                var read = readBuffer.read(allocatebyte, 0, 4096);
                                console.log("read:" + read);
                                //console.log("allocatebyte:" + allocatebyte.toString());
                                var StringCls = Java.use("java.lang.String");
                                console.log("allocate明文:" + StringCls.$new(allocatebyte, "UTF-8"));
                            } catch (error) {
                                console.log("[!] 读取数据流失败: " + error.stack);
                            }
                            allocate.limit(read);
                            size -= read;
                            vfP.A00.value += read;
                            allocate.rewind();
                            vfP.A02.value.onBody(allocate);
                            allocate.clear();
                        }
                    }
                } catch (e) {
                    if (e instanceof IOException || e instanceof IllegalStateException) {
                        const X2wl = Java.use("X.2wl");
                        X2wl.A07("LigerAsyncInterface_body", e);
                    } else {
                        console.log("[!] 模拟出错: " + e.stack);
                    }
                }
                //this.run(); 
            }
        }

        var body_data = []
        let G1A = Java.use("X.G1A");
        const FileOutputStream = Java.use("java.io.FileOutputStream");

        G1A["run"].implementation = function () {
            // 标记是否是我们关心的请求
            var isTarget = false;

            try {
                // 1. 获取 URL 判断
                var vfP = Java.cast(this.A00.value, Java.use("X.VfP"));
                var vfpA08 = vfP.A08.value;
                var j7tA08 = vfpA08.A08.value;

                if (j7tA08.toString().indexOf("fbsearch/reels_serp") !== -1) {
                    isTarget = true;
                    console.log("========== 命中 Reels 请求，接管数据流 ==========");

                    // 2. 准备变量
                    var readBuffer = vfP.A06.value;
                    const ByteBuffer = Java.use("java.nio.ByteBuffer");

                    // 创建给 App 用的 ByteBuffer
                    var allocate = ByteBuffer.allocate(4096);

                    var size = readBuffer.size();
                    console.log("初始数据量 size: " + size);
                    if (size <= 0) {
                        console.log("没数据");
                        console.log("[!] url :"+ j7tA08.toString());
                        return this.run();
                    }
                    vfP.A00.value += size;
                    var oneAPIResult = "";
                    // 3. 开始接管循环
                    while (size > 0) {
                        // 创建一个临时的 Java byte[] 用于承载数据
                        // 这是关键！我们需要一个中间容器
                        var tempByteArray = Java.array('byte', new Array(4096).fill(0));

                        // 从源头读取数据到 tempByteArray
                        var read = readBuffer.read(tempByteArray, 0, 4096);
                        // ---------------------------------------------------------
                        // 【你的操作区域】在这里你拥有了数据的拷贝 tempByteArray
                        // ---------------------------------------------------------
                        try {
                            var StringCls = Java.use("java.lang.String");
                            // 这里是你拿到的明文，你可以存文件、打印、做任何事
                            var myData = StringCls.$new(tempByteArray, 0, read, "UTF-8");
                            oneAPIResult+=myData;
                            //console.log("[你的数据副本]: " + myData.substring(0, 100));
                        } catch (err) {
                            console.log("数据处理错误: " + err);
                        }

                        // ---------------------------------------------------------
                        // 【修复 APP 逻辑】把数据填回 ByteBuffer
                        // ---------------------------------------------------------
                        // 必须先清空指针

                        allocate.clear();
                        // 把读到的 byte[] 塞进 ByteBuffer，这一步你之前漏了！

                        allocate.put(tempByteArray, 0, read);
                        // 重置指针，准备让 App 读取

                        allocate.flip();

                        // ---------------------------------------------------------
                        // 【发送给 APP】
                        // ---------------------------------------------------------
                        allocate.limit(read);

                        size -= read;

                        vfP.A00.value += read;

                        allocate.rewind();

                        try {
                            var clazz = vfP.getClass();
                            var field = clazz.getDeclaredField("A02");
                            field.setAccessible(true);
                            var realA02 = field.get(vfP);
                            // console.log("A02 字段真实类名:", realA02.$className);
                            // var methods = realA02.getClass().getDeclaredMethods();
                            // for (var i = 0; i < methods.length; i++) {
                            //     console.log("method:", methods[i].getName());
                            // }
                            var YEA = Java.use("X.YEA");
                            var realA02_cast = Java.cast(realA02, YEA);
                            realA02_cast.onBody(allocate);

                        } catch (e) {
                            console.log("[!] 模拟出错: " + e.stack);
                        }
                        allocate.clear();


                    }
                    //console.log("拼接好的结果："+oneAPIResult);
                    try {
                        send({
                            "url":j7tA08.toString(),
                            "data":oneAPIResult,
                        })
                    } catch (e) {
                        console.log("写入文件错误："+e.stack);
                    }
                    // 循环结束，不要调用 this.run()，因为我们已经跑完了逻辑
                    console.log("========== 数据流处理完毕 ==========");
                }
            } catch (e) {
                // 如果出错，打印日志
                if (e instanceof java.io.IOException || e.toString().indexOf("IOException") !== -1) {
                    // 模拟源码的异常处理
                    try {
                        const X2wl = Java.use("X.2wl");
                        X2wl.A07("LigerAsyncInterface_body", e);        
                        console.log("X2wl.A07被调用");
                    } catch (ex) { }
                } else {
                    console.log("[!] 脚本逻辑错误: " + e + "\n" + e.stack);
                }
            }
            
            // 对于非目标请求，或者出错的情况，执行原始逻辑，防止 App 崩溃
            //this.run();
        }
    } catch (eMeesage) {
        console.log("hook函数失败：" + eMeesage.stack)
    }
})